package com.atguigu.gmall.activity.component;

import com.atguigu.gmall.activity.service.SeckillService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import sun.security.ssl.SSLContextImpl;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 监听通知事件
 */
@Component
public class SeckillLocalCache implements MessageListener {

    public static final String channel_key = "seckillgoodsup";
    public static final String goods_up = "up";

    @Autowired
    SeckillService seckillService;

    /**
     * 准备一个保存需要秒杀的所有商品的集合
     */
    private Map<Long, SeckillGoods> cache = new ConcurrentHashMap<>();

    /**
     * 返回当天所有需要秒杀的商品
     *
     * @return
     */
    public List<SeckillGoods> todaySeckillGoods(){
        List<SeckillGoods> values = getCacheGoods();
/*      //按skuId大小排序
       List<SeckillGoods> collect =
                values.stream()
                        .sorted((t1, t2) -> Math.toIntExact(t1.getSkuId() - t2.getSkuId()))
                        .collect(Collectors.toList());*/
        //map中按照秒杀事件排序
        if (!CollectionUtils.isEmpty(values)){
            return values;
        } else {
            //查询redis数据，重新同步
            cacheReload();
            return getCacheGoods();

        }

    }

    private List<SeckillGoods> getCacheGoods(){
        Collection<SeckillGoods> values = cache.values();
        if (CollectionUtils.isEmpty(values)){
            return null;
        } else{
            List<SeckillGoods> collect = values.stream()
                    .sorted(Comparator.comparingLong(t -> t.getStartTime().getTime())).collect(Collectors.toList());
            return collect;
        }
    }

    /**
     * 从缓存中获取秒杀商品
     * @param skuId
     * @return
     */
    public SeckillGoods getSeckillGoodsBySkuId(Long skuId){
        SeckillGoods goods = cache.get(skuId);
        if (goods == null && cache.size() == 0){
            cacheReload();
            goods = cache.get(skuId);
        }
        return goods;
    }

    /*
    可能由于机器重启缓存要重新加载
     */
    private void cacheReload(){
        List<SeckillGoods> currentSeckillGoods = seckillService.getCurrentSeckillGoods();
        //上架到本地二级缓存
        if (!CollectionUtils.isEmpty(currentSeckillGoods)){
            for (SeckillGoods good : currentSeckillGoods) {
                cache.put(good.getSkuId(),good);
            }
        }
    }



    /**
     * redis消息到达
     * @param message 消息内容
     * @param pattern 通道名 seckillgoodsup
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String channel = new String(message.getChannel());
        String body = new String(message.getBody());
        if (channel.equals(channel_key)){
            if (goods_up.equals(body)){
                //redis中有定时任务把当天的商品上架了
                //TODO 同步需要秒杀的商品到本地缓存
                //清除前一天的本地缓存数据
                cache.clear();
                System.out.println("监听到当天需要上架的所有商品的内容已经缓存");
                cacheReload();
            }
        } else if (channel.equals(RedisConst.SECKILL_GOODS_OUT)){
            //广播的内容就是skuId没有库存了
            long skuId = Long.parseLong(body);
            SeckillGoods goods = cache.get(skuId);
            goods.setStockCount(goods.getNum());
        }
    }
}
